主题
对比小林《RDB 快照》《AOF 持久化》、JavaGuide Redis 持久化与面渣逆袭《Redis 持久化》(侧边栏进入)。
多版对比
机制链,小林最完整:RDB 全量二进制快照,bgsave 靠 fork + 写时复制(COW)——fork 只复制页表所以快,主进程继续写,极端情况全部写时内存翻倍、快照期间的修改不在这次快照里;AOF 先执行命令后记日志(不阻塞当前命令、免语法检查),代价是可能丢数据并阻塞下一条命令。三种写回策略的本质是 fsync 时机:Always 同步刷盘、Everysec 异步每秒、No 交给操作系统——可靠性递减、性能递增。AOF 重写由子进程做,把当前状态化成一条命令,主进程期间双写 AOF 缓冲区和重写缓冲区,完成时信号处理函数追加增量(这一步阻塞)。
工程纠偏,JavaGuide 独有:「everysec 最多丢 1 秒」不严谨——磁盘忙时主线程会被强制阻塞最多 2 秒,盯 aof_delayed_fsync;fork 延迟与实例大小相关(>50GB 常超 1 秒);THP 开启会让 COW 放大 512 倍甚至 OOM;Redis 7.0 的 Multi-Part AOF(base + incr + manifest)消除了重写期间的双写,manifest 损坏是新单点;选型建议「主节点关持久化、从节点开 AOF」要谨慎评估。
面渣:结论式覆盖(save 阻塞 / bgsave 子进程、恢复优先加载 AOF、4.0 混合持久化)——适合搭骨架,机制没展开。
混合持久化的时机,三方一致但小林讲得最清:发生在 AOF 重写时——重写文件前半段是 RDB 格式的全量、后半段是增量 AOF,加载快、丢得少。
最优题解
Redis 持久化两条路:RDB 是全量快照,bgsave 用 fork + 写时复制,主进程几乎不阻塞,恢复快,但两次快照之间的数据会丢;AOF 是命令日志,先执行后记录,靠三种 fsync 策略平衡安全与性能——always 不丢但慢、everysec 是默认(说「最多丢 1 秒」其实不严谨,磁盘卡住可能阻塞主线程 2 秒)、no 交给系统。AOF 文件太大触发重写:子进程把当前内存状态固化成最小命令集,期间新写入同时进缓冲区,结束后追加增量。
生产上用 4.0+ 的混合持久化:重写时前半 RDB 全量 + 后半 AOF 增量,加载快丢得少。两个工程要点必须主动讲:fork 的代价和实例大小成正比(大实例要监控 fork 延迟,并关掉 THP,否则写时复制放大 512 倍可能 OOM);大 Key 会同时拖慢 fsync 和 COW,是持久化问题的常见根因。
追问链
追问:RDB 和 AOF 同时开,恢复用哪个? 参考答:优先 AOF——丢的数据更少;混合持久化下加载的是「RDB 全量 + AOF 增量」的混合文件,兼得恢复速度和数据完整性。
追问:为什么 AOF 重写期间还能写入? 参考答:重写用的是子进程,遍历当前内存生成新文件,主进程照常服务;期间的新写入进入 AOF 缓冲区和重写缓冲区两份,重写完成后增量追加进去——最后的追加动作会短暂阻塞。
我的理解
这题的层次:背「RDB 快、AOF 全」是面渣水平;讲清 fork+COW 和 fsync 时机是小林水平;说出「everysec 不等于只丢 1 秒」「THP 要关」「7.0 Multi-Part AOF」是 JG 水平——后三条正是面试官的第二三追问。大 Key 对持久化的影响(小林独有)是我项目里真实会踩的点,值得带进回答。